/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * SPIDevice.h
 * The SPI Device class
 * Copyright (C) 2013 Simon Newton
 */

#ifndef PLUGINS_SPI_SPIDEVICE_H_
#define PLUGINS_SPI_SPIDEVICE_H_

#include <string>
#include <vector>
#include <set>

#include "olad/Device.h"
#include "ola/io/SelectServer.h"
#include "ola/rdm/UID.h"
#include "ola/rdm/UIDAllocator.h"

namespace ola {
namespace plugin {
namespace spi {

class SPIDevice: public ola::Device {
  public:
    SPIDevice(class SPIPlugin *owner,
              class Preferences *preferences,
              class PluginAdaptor *plugin_adaptor,
              const string &spi_device,
              ola::rdm::UIDAllocator &uid_allocator);

    string DeviceId() const;

    bool InitSPI();
    void WriteToSPIBuffer(unsigned int port_id, unsigned int byte_count, const uint8_t* data);

    /**
     * The number of bytes used per pixel.
     *
     * TODO: This needs to be abstracted if support for pixels requiring a different number of bytes
     * are added.
     */
    static const uint16_t SLOTS_PER_PIXEL;

  protected:
    bool StartHook();
    void PrePortStop();

  private:
    class Preferences *m_preferences;
    class PluginAdaptor *m_plugin_adaptor;
    
    string m_spi_device_name;
    string m_spi_device_path;
    int m_spi_speed;

    /**
     * Total number of pixels connected to this device
     */
    int m_total_pixel_count;

    /**
     * Number of pixels controlled by each port
     */
    int m_pixels_per_port;

    /**
     * Number of ports
     */
    int m_port_count;

    /**
     * Multiplexing mode. Must be one of MUX_MODES
     */
    string m_mux_mode;

    /*
     * File Descriptor for the SPI Device
     */
    int m_fd;

    /* Shared Buffer Mux Mode Members */
    /**
     * Shared data buffer for all pixels.
     */
    uint8_t* m_shared_spi_buffer;

    /**
     * Size of the shared buffer.
     */
    int m_shared_spi_buffer_size;

    void FlushSharedSPIBuffer() const;

    string PersonalityKey(int port_id) const;
    string StartAddressKey(int port_id) const;

    string SPISpeedKey() const;
    string MuxModeKey() const;
    string PixelsPerPortKey() const;
    string PixelCountKey() const;

    static const char SPI_DEVICE_NAME[];

    static const string MUX_MODE_SHARED_BUFFER;

    static const uint8_t SPI_MODE;
    static const uint8_t SPI_BITS_PER_WORD;
    static const uint16_t SPI_DELAY;
    static const uint32_t SPI_SPEED;
};
}  // spi
}  // plugin
}  // ola
#endif  // PLUGINS_SPI_SPIDEVICE_H_
